import { NOOP } from '@/utils'

export function useRequest(asyncFn, options = {}) {
  const {
    params,
    config,
    immediate = false,
    shallow = true,
    initialData,
    onSuccess,
    onError = NOOP,
    onFinished = NOOP
  } = options

  const rawData = ref() // response.data
  const data = (shallow ? shallowRef : ref)(initialData) // response.data.data
  const count = ref(0)
  const error = ref()
  const isLoading = ref(false)
  const isFinished = ref(false)

  function loading(loading) {
    isLoading.value = loading
    isFinished.value = !loading
  }

  function execute(_params = toValue(params), _config = config) {
    error.value = undefined
    loading(true)
    return asyncFn(_params, _config)
      .then(res => {
        rawData.value = res

        if (res?.code === 200) {
          if (onSuccess) {
            onSuccess(res.data)
          } else {
            data.value = res.data
            count.value = res.count ?? 0
          }
          return res.data
        }
        handleError(res?.message ?? res.msg)
        return Promise.reject(res?.message ?? res.msg)
      })
      .catch(err => {
        handleError(err?.message)
        return Promise.reject(err?.message)
      })
      .finally(() => handleFinished())
  }

  function handleFinished() {
    loading(false)
    onFinished()
  }

  function handleError(errMsg = '未知错误') {
    error.value = errMsg
    onError(errMsg)
  }

  immediate && execute()

  return {
    execute,
    refresh: execute,
    rawData,
    data,
    count,
    error,
    isLoading,
    isFinished
  }
}
